<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Interceptors</title>
  </head>
  <body>
    <script>
      // Axios
      function Axios(config) {
        this.defaults = config;
        this.interceptors = {
          request: new InterceptorManage(),
          response: new InterceptorManage(),
        };
      }

      // request
      Axios.prototype.request = function (config) {
        // 返回一个promise
        let promise = Promise.resolve(config);

        let chian = [dispatchRequest, undefined];

        // 请求拦截器
        this.interceptors.request.forEach(function (interceptor) {
          chian.unshift(interceptor.fulfilled, interceptor.rejected);
        });
        // 响应拦截器
        this.interceptors.response.forEach(function (interceptor) {
          chian.push(interceptor.fulfilled, interceptor.rejected);
        });

        // console.log(chian);

        while (chian.length) {
          promise = promise.then(chian.shift(), chian.shift());
          // console.log(promise.then((res) => console.log(res)));
        }

        return promise;
      };

      // dispatchRequest
      function dispatchRequest(config) {
        // 模拟一个promise请求，不是完整的流程，dispatchRequest还应该调用adapter

        return new Promise((resolve, reject) => {
          resolve({
            status: 200,
            statusText: "ok",
            config: config,
          });
        });
      }

      // ============================

      // 拦截器管理器，负责实例化拦截器，添加一些prototype方法
      function InterceptorManage() {
        this.handlers = [];
      }
      InterceptorManage.prototype.use = function use(fulfilled, rejected) {
        this.handlers.push({
          fulfilled,
          rejected,
        });
      };
      InterceptorManage.prototype.forEach = function forEach(fn) {
        // h 是当前遍历数组的拦截器对象
        // console.log(fn);
        this.handlers.forEach((h) => {
          if (h != null) {
            // console.log(h);
            fn(h);
          }
        });
      };

      // ============================
      // 测试代码

      let context = new Axios({});
      let axios = Axios.prototype.request.bind(context);

      Object.keys(context).forEach((key) => {
        axios[key] = context[key];
      });

      axios.interceptors.request.use(
        function one(config) {
          console.log(config);
          // console.log("request 拦截器1号");
          return config;
        },
        function one(error) {
          return Promise.reject(error);
        }
      );
      axios.interceptors.response.use(
        function two(response) {
          // console.log("response 拦截器1号");
          console.log(response);
          return response;
        },
        function two(error) {
          return Promise.reject(error);
        }
      );

      // console.dir(axios);

      axios({
        method: "get",
        url: "https://yesno.wtf/api",
      }).then((response) => {
        // console.log(response);
      });
    </script>
  </body>
</html>
